<template>
  <div class="square">
    <div class="square-header">
      <div class="title">合同上传 比对差异</div>
      <div>精准比对文档增删改查，高亮定位差异信息</div>
    </div>
    <div class="square-body">
      <!-- 左侧上传区域 -->
      <div class="upload-container">
        <el-upload class="upload-demo" drag :before-upload="handleBeforeUploadLeft" :show-upload-list="false" :limit="1"
          action="" multiple>
          <div class="uplod-title">主板</div>
          <img src="@/assets/images/file.png" width="60px" height="60px" />
          <div class="el-upload__text">
            点击或将文件拖拽到这里上传
          </div>
        </el-upload>
        <div v-if="fileLeftName" class="uploaded-file-info">
          <span>{{ fileLeftName }}</span>
          <div class="del-text" @click="removeFile('left')">删除</div>
        </div>
      </div>

      <!-- 右侧上传区域 -->
      <div class="upload-container">
        <el-upload class="upload-demo" :limit="1" drag :before-upload="handleBeforeUploadRight"
          :show-upload-list="false" action="" multiple>
          <div class="uplod-title">副板</div>
          <img src="@/assets/images/file.png" width="60px" height="60px" />
          <div class="el-upload__text">
            点击或将文件拖拽到这里上传
          </div>
        </el-upload>
        <div v-if="fileRightName" class="uploaded-file-info">
          <span>{{ fileRightName }}</span>
          <div class="del-text" @click="removeFile('right')">删除</div>
        </div>
      </div>
    </div>
    <div class="square-footer">
      <el-button type="primary" @click="startComparison" :disabled="!fileLeft || !fileRight">开始合同比对</el-button>
    </div>
    <el-dialog v-model="dialogVisible" width="1200px">
      <div class="document-header">
        <h3>合同对比</h3>
        <h3 class="header-right">{{ isContent ? '总结' : '差异报告' }}</h3>
      </div>
      <div class="comparison-view">


        <!-- 文档比较区域 -->
        <div class="document-comparison">
          <div class="document-left" ref="left" @scroll="handleScroll('left')">
            <div v-html="documentContentLeft"></div>
          </div>
          <div class="document-right" ref="right" @scroll="handleScroll('right')">
            <div v-html="documentContentRight"></div>
          </div>
          <div class="difference-report" ref="reportDocument" v-loading="loading" @scroll="handleScroll('report')">
            <div v-if="!isContent" v-html="differenceReport"></div>
            <div v-else v-html="markdown.render(differenceReport)"></div>
          </div>
        </div>
      </div>

      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" @click="recompare">重新比对</el-button>
          <el-button type="primary" @click="handEnd">{{ isContent ? '报告差异' : '总结' }}</el-button>
          <el-button  type="primary" @click="toggleSyncScroll">{{ syncScroll ? '停止同步滚动' : '开始同步滚动' }}</el-button>
          <el-button @click="dialogVisible = false">关闭</el-button>

        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, ComponentInternalInstance, getCurrentInstance } from 'vue';
import mammoth from 'mammoth';
import * as DiffMatchPatch from 'diff-match-patch';
import { ElMessage } from 'element-plus';
import MarkdownIt from 'markdown-it';

const markdown = new MarkdownIt();
const { proxy } = getCurrentInstance() as ComponentInternalInstance;

// 定义响应式数据
const documentContentLeft = ref('');
const documentContentRight = ref('');
const fileLeft = ref<File | null>(null);
const fileRight = ref<File | null>(null);
const dialogVisible = ref(false);
const differenceReport = ref('');
const fileLeftName = ref('');
const fileRightName = ref('');
const isContent = ref(false);
const aiContent = ref('');
const loading = ref(false); // 加载状态
const maxRetries = 10; // 最大重试次数
const retryInterval = 3000; // 每次重试间隔时间（毫秒）

/**
 * 提取HTML中的纯文本
 * @param {String} html - HTML字符串
 */
const extractTextFromHtml = (html: string) => {
  const tempDiv = document.createElement('div');
  tempDiv.innerHTML = html;
  return tempDiv.textContent || tempDiv.innerText || '';
};

/**
 * 处理左侧文件上传前的操作
 * @param {File} file - 上传的文件对象
 */
const handleBeforeUploadLeft = (file: File) => {
  fileLeft.value = file;
  fileLeftName.value = file.name;
  convertDocxToHtml(file, 'left');

  return false; // 阻止自动上传
};

/**
 * 处理右侧文件上传前的操作
 * @param {File} file - 上传的文件对象
 */
const handleBeforeUploadRight = (file: File) => {
  fileRight.value = file;
  fileRightName.value = file.name;
  convertDocxToHtml(file, 'right');

  return false; // 阻止自动上传
};

/**
 * 删除文件
 * @param {String} side - 左侧还是右侧 ('left' 或 'right')
 */
const removeFile = (side: 'left' | 'right') => {
  if (side === 'left') {
    fileLeft.value = null;
    fileLeftName.value = '';
  } else if (side === 'right') {
    fileRight.value = null;
    fileRightName.value = '';
  }
};

/**
 * 将.docx文件转换为HTML并显示
 * @param {File} file - .docx文件对象
 * @param {String} side - 左侧还是右侧 ('left' 或 'right')
 */
const convertDocxToHtml = (file: File, side: 'left' | 'right') => {
  const reader = new FileReader();
  reader.onload = (e) => {
    const arrayBuffer = e.target?.result;
    if (arrayBuffer) {
      mammoth.convertToHtml({ arrayBuffer })
        .then((result) => {
          if (side === 'left') {
            documentContentLeft.value = result.value;
          } else if (side === 'right') {
            documentContentRight.value = result.value;
          }
        })
        .catch((error) => {
          console.error('Error during conversion: ', error);
        });
    }
  };
  reader.readAsArrayBuffer(file); // 以ArrayBuffer格式读取文件
};

/**
 * 开始合同比对
 */
const startComparison = () => {
  if (fileLeft.value && fileRight.value) {
    generateDifferenceReport();
    dialogVisible.value = true;
    isContent.value = false
  }
};

/**
 * 生成差异报告
 */
let report = ref('');
const aiText = ref()
const generateDifferenceReport = async () => {
  const dmp = new DiffMatchPatch.diff_match_patch();

  // 提取纯文本

  const textLeft = delImg(documentContentLeft.value)
  const textRight = delImg(documentContentRight.value)
  const textLeft1 = extractTextFromHtml(documentContentLeft.value);
  const textRight2 = extractTextFromHtml(documentContentRight.value);
  const diffs = dmp.diff_main(textLeft, textRight);
  const diffs2 = dmp.diff_main(textLeft1, textRight2);
  dmp.diff_cleanupSemantic(diffs);
  dmp.diff_cleanupSemantic(diffs2);
  console.log("diffs", diffs)


  const diffData = ref({
    add: [],
    del: []
  });


  diffs2.forEach(([op, text]) => {
    if (op === 1) { // 插入
      aiText.value += escapeHtml(text)
      // aiText.value += `<span style="color:green">${escapeHtml(text)}</span>`;
    } else if (op === -1) { // 删除
      aiText.value += escapeHtml(text)
      // aiText.value += `<span style="color:red">${escapeHtml(text)}</span>`;
    } else { // 相同
      aiText.value += escapeHtml(text)
    }
  })

  diffs.forEach(([op, text]) => {
    if (!text || !text.trim()) return; // 如果文本为空或全是空白字符，则跳过
    if (op === 1) { // 插入
      console.log("新增", text)
      differenceReport.value +=      `<span style="color:green">${text}</span>`;
      diffData.value.add.push(text);
    } else if (op === -1) { // 删除
      console.log("删除", text)
      diffData.value.del.push(text);
      differenceReport.value += `<span style="color:red">${text}</span>`;
    } else { // 相同

      differenceReport.value += text
    }
  });
  report.value = differenceReport.value;
  documentContentLeft.value = delImg(documentContentLeft.value);
  documentContentRight.value = delImg(documentContentRight.value);
  console.log('diffData.value',diffData.value.add)
  console.log('diffData.value',diffData.value.del)
  await sendMessage(diffData.value);
};


// 去除图片和a链接
const delImg = (str) => {
  let result = str.replace(/<img[^>]*>/g, '');
  result = result.replace(/<a[^>]*>(.*?)<\/a>/g, '$1');
  return result
}

const conversation_id = ref('')
const sendMessage = async (sendText: any) => {
  const res = await proxy?.$api.post(`http://10tz44994vg46.vicp.fun/v1/chat-messages`, {
    "inputs": {},
    "query": '根据删除和新增项来总结这个合同的差异' + JSON.stringify(sendText),
    "response_mode": "streaming",
    "conversation_id": conversation_id.value,
    "user": "123",
   

  }, {
    headers: {
      'Authorization': 'Bearer app-q1WQIYFgyDI4yjbeV2h6PYMi',
      "Content-Type": "application/json"
    },
  })
  // 使用正则表达式匹配 conversation_id 的值
  const match = res.match(/"conversation_id"\s*:\s*"([^"]*)"/);
  const conversationId = match ? match[1] : null;
  conversation_id.value = conversationId
  return res
}







const getMessagesWithRetry = async (retryCount = 0): Promise<string | null> => {
  loading.value = true;
  try {
    const res = await proxy?.$api.get(`http://10tz44994vg46.vicp.fun/v1/messages?user=123&last_id=&limit=20&conversation_id=${conversation_id.value}`, {
      "order": "ASC"
    }, {
      headers: {
        'Authorization': 'Bearer app-q1WQIYFgyDI4yjbeV2h6PYMi',
        "Content-Type": "application/json"
      },
    })
    if (res.data) {
      loading.value = false;
      aiContent.value = res.data[0].answer;
      if (isContent.value) {
        differenceReport.value = aiContent.value || '';
      } else {
        differenceReport.value = report.value;
      }
      console.log('aiContent.value', aiContent.value)
    } else if (retryCount < maxRetries) {
      setTimeout(() => {
        getMessagesWithRetry(retryCount + 1);
      }, retryInterval);
    } else {
      loading.value = false;

      return null;
    }
  } catch (error) {
    loading.value = false;
    return null;
  }
};
const handEnd = async () => {
  isContent.value = !isContent.value;
  differenceReport.value = ''
  await getMessagesWithRetry();
};

const escapeHtml = (str: string) => {
  return str.replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;');
};


const syncScroll = ref(false); // 控制是否同步滚动

// 获取DOM元素引用
const left = ref<HTMLElement | null>(null);
const right = ref<HTMLElement | null>(null);
const reportDocument = ref<HTMLElement | null>(null);

/**
 * 切换同步滚动状态
 */
const toggleSyncScroll = () => {
  syncScroll.value = !syncScroll.value;
};

/**
 * 处理滚动事件
 * @param source - 触发滚动的源 ('left', 'right', 'report')
 */
const handleScroll = (source: 'left' | 'right' | 'report') => {
  if (!syncScroll.value) return;

  const getScrollTop = (element: HTMLElement | null) => element?.scrollTop || 0;
  const setScrollTop = (element: HTMLElement | null, value: number) => {
    if (element) element.scrollTop = value;
  };

  let scrollTop = 0;
  switch (source) {
    case 'left':
      scrollTop = getScrollTop(left.value);
      break;
    case 'right':
      scrollTop = getScrollTop(right.value);
      break;
    case 'report':
      scrollTop = getScrollTop(reportDocument.value);
      break;
  }

  if (left.value && left.value !== document.activeElement) setScrollTop(left.value, scrollTop);
  if (right.value && right.value !== document.activeElement) setScrollTop(right.value, scrollTop);
  if (report.value && reportDocument.value !== document.activeElement) setScrollTop(reportDocument.value, scrollTop);
};

/**
 * 重新比对
 */
const recompare = () => {
  dialogVisible.value = false;
  fileLeft.value = null;
  fileRight.value = null;
  fileLeftName.value = '';
  fileRightName.value = '';
  documentContentLeft.value = '';
  documentContentRight.value = '';
  differenceReport.value = '';
};
</script>

<style lang="scss" scoped>
.square-header {
  display: flex;
  justify-content: center;
  flex-direction: column;
  font-size: 16px;
  margin-top: 50px;
  margin-bottom: 50px;
  text-align: center;
}

.dialog-footer {
  display: flex;
  justify-content: center;
  text-align: center;
}

.title {
  margin: 10px 0;
  font-weight: 700;
}

.square-body {
  display: flex;
  justify-content: space-between;
  width: 1000px;
  margin: 20px auto;
}

.upload-container {
  width: 500px;

}

:deep(.el-upload-dragger) {
  width: 500px;
  height: 300px;
  background-color: #fafafa;
}

.uploaded-file-info {
  margin-top: 10px;
  font-size: 14px;
  height: 20px;
  display: flex;
  gap: 10px;
  justify-content: center;
  color: #606266;
}

.del-text {
  color: blue;
  cursor: pointer;
}

.square-footer {
  display: flex;
  margin-top: 10px;
  justify-content: center;
}

.upload-demo {
  width: 500px;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
  flex-direction: column;
}

.upload-demo img {
  position: relative;
  top: -100px;
}

.el-upload__text {
  position: relative;
  top: -100px;
}

.document-text {
  font-size: 12px;
}

.comparison-view {
  display: flex;
  height: 60vh;
}

.document-comparison {
  display: flex;
  width: 100%;
  height: 100%;
  flex-direction: row;
}

.uplod-title {
  font-size: 24px;
  font-weight: 700;
}

.document-header {
  display: flex;
  justify-content: space-between;
}

.header-right {
  position: relative;
  right: 330px;
}

.difference-report,
.document-left,
.document-right {
  width: 500px;
  height: 100%;
  overflow-y: auto;
  padding: 10px;
  border: 1px solid #ccc;
}

.document-left {
  border-right: none;
}

.document-right {
  border-left: none;
}

:deep(.el-dialog__header) {
  margin: 10px;
  padding: 10px;
  height: 0px;
}
</style>